package city.spring.modules.work.action;

import city.spring.modules.work.action.handler.IHandler;
import city.spring.modules.work.action.model.AbstractPlanUser;
import city.spring.modules.work.action.model.ResultItem;
import com.google.common.collect.Table;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDate;

/**
 * 排班人员规则处理器
 *
 * @author HouKunLin
 * @date 2020/6/5 0005 10:05
 */
@Data
public class WorkPlanRuleHandler<SHIFT, USER> {
    private static final Logger logger = LoggerFactory.getLogger(WorkPlanRuleHandler.class);
    /**
     * 所有的排班记录表
     */
    private final Table<LocalDate, Object, ResultItem<SHIFT, USER>> resultTable;
    /**
     * 判断操作
     */
    private final IHandler<SHIFT, USER>[] actions;
    /**
     * 错误次数
     */
    private int errorSum = 0;

    public WorkPlanRuleHandler(Table<LocalDate, Object, ResultItem<SHIFT, USER>> resultTable, IHandler<SHIFT, USER>[] actions) {
        this.resultTable = resultTable;
        this.actions = actions;
    }

    /**
     * 判断是否全部成功（全部条件都满足）
     *
     * @param people 判断该人员是否可以安排排班
     * @return 结果，true可以安排排版，false该人员无法安排排班
     */
    public boolean isSuccess(LocalDate rowKey, Object colKey, AbstractPlanUser<USER> people, int retryNumber, boolean openLogger) {
        if (!people.canUse()) {
            incrementErrorNumber();
            return false;
        }
        for (int i = 0; i < actions.length; i++) {
            IHandler<SHIFT, USER> action = actions[i];
            // result 返回 true 表示不通过， 返回 false 表示通过
            boolean result = action.run(resultTable, rowKey, colKey, people);
            if (result) {
                // 统计总错误次数
                incrementErrorNumber();
                if (openLogger && logger.isErrorEnabled() && retryNumber > 0) {
                    logger.error("错误次数{}，重试{}次错误 {} {}  actions[{}]=false actionType={} {}",
                            errorSum, retryNumber, rowKey, colKey, i, action.getClass().getSimpleName(), people);
                }
                return false;
            }
        }
        return true;
    }

    private void incrementErrorNumber() {
        errorSum++;
    }
}
